package com.q.tqb.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
import android.widget.Toast;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.q.tqb.R;
import com.q.tqb.util.LogUtil;
import com.q.tqb.view.dialog.CustomProgressDialog;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.LinkedHashMap;


/**
 * Created by Administrator on 2017/12/20.
 */
public class SoundButton extends Button {


    //三个对话框的状态常量
    private static final int STATE_DOWN = 1;
    private static final int STATE_UP = 2;
    private static final int STATE_WANT_TO_CANCEL = 3;


    //垂直方向滑动取消的临界距离
    private static final int DISTANCE_Y_CANCEL = 50;
    //取消录音的状态值
    private static final int MSG_VOICE_STOP = 4;

    // 正在录音标记
    private boolean isRecording = false;
    //录音对话框
    private DialogManager mDialogManager;
    //上下文
    private Context mContext;


    // 三个状态


    private boolean isReady;
    private boolean isActionUp;
    private boolean isCanRecord;
    private SpeechRecognizer mIat;
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
    private int mCurrentState = STATE_UP;
    private CustomProgressDialog mProgressDialog;
    private boolean isNormal = false;


    public SoundButton(Context context) {
        this(context, null);
    }

    public SoundButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SoundButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        isCanRecord = true;
        mIat = SpeechRecognizer.createRecognizer(mContext, mInitListener);
        mDialogManager = new DialogManager(getContext());
        mProgressDialog = new CustomProgressDialog(getContext());
    }


    public void setParam() {
        mIat.setParameter(SpeechConstant.PARAMS, null);
        String mEngineType = SpeechConstant.TYPE_CLOUD;
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
        // 设置语言
        mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        mIat.setParameter(SpeechConstant.TRANS_LANG, "cn");


        // 设置语音前端点:静音超时时间，即用户多长时间不说话则当做超时处理
        mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
        // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音
        //   mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mIat.setParameter(SpeechConstant.ASR_PTT, "0");
        // 注：AUDIO_FORMAT参数语记需要更新版本才能生效
        mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/tqb/iat.wav");

    }


    @SuppressLint("HandlerLeak")
    private Handler stateHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    isReady = true;
                    if (!isActionUp) {
                        //开始录音
                        mDialogManager.showRecordingDialog();
                        isRecording = true;
                        mIatResults.clear();
                        setParam();
                        int ret = mIat.startListening(mRecognizerListener);
                        if (ret != ErrorCode.SUCCESS) {
                            Toast.makeText(mContext, "\"听写失败,错误码：\" + ret", Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        isCanRecord = true;
                    }
                    break;
                case MSG_VOICE_STOP:
                    //超时
                    mDialogManager.dimissDialog();
                    break;
                case 99:
                    mDialogManager.dimissDialog();
                    break;
                default:
                    break;

            }
        }
    };


    //手指滑动监听
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //响应DOWN事件进行录音准备。放到这里会有问题，比如用户故意连续点击多次，就会出现各种问题。
                changeState(STATE_DOWN);
                if (isCanRecord) {
                    isNormal = false;
                    isCanRecord = false;


                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
                                vibrator.vibrate(30);
                                Thread.sleep(300);
                                stateHandler.sendEmptyMessage(0);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isRecording) {
                    // 根据x，y来判断用户是否想要取消
                    if (wantToCancel(x, y)) {
                        mCurrentState = STATE_WANT_TO_CANCEL;
                        changeState(STATE_WANT_TO_CANCEL);

                    } else {
                        //  if (!isOverTime)
                        // changeState(STATE_RECORDING);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                changeState(STATE_UP);
                if (isReady) {
                    if (mCurrentState == STATE_WANT_TO_CANCEL) {
                        mIat.cancel();
                        mDialogManager.dimissDialog();
                        mCurrentState = STATE_DOWN;
                    } else {
                        isNormal = true;
                        mIat.stopListening();
                        mDialogManager.dimissDialog();
                        mCurrentState = STATE_DOWN;
                        mProgressDialog.show();
                    }
                }
                break;
            default:
                break;

        }

        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                getParent().requestDisallowInterceptTouchEvent(false);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    private boolean wantToCancel(int x, int y) {
        // 判断是否在左边，右边，上边，下边
        if (x < 0 || x > getWidth()) {
            return true;
        }
        if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
            return true;
        }
        return false;
    }

    private void changeState(int state) {
        switch (state) {
            case STATE_DOWN:
                isReady = false;
                isActionUp = false;
                setBackground(ContextCompat.getDrawable(mContext, R.drawable.shape_btn_pale_red));
                setText("松开发送语音");
                break;
            case STATE_UP:
                isCanRecord = true;
                setText("读取口令 领取现金红包");
                setBackground(ContextCompat.getDrawable(mContext, R.drawable.shape_btn_red));
                isActionUp = true;
                break;
            case STATE_WANT_TO_CANCEL:
                //松开取消
                setText(R.string.release_cancel);
                // dialog want to cancel
                mDialogManager.wantToCancel();
                break;
            default:
                break;

        }


    }

    /**
     * 初始化监听器。
     */
    private InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {
            if (code != ErrorCode.SUCCESS) {
                LogUtil.i("onInit: " + "初始化失败，错误码：" + code);
            } else {
                LogUtil.i("onInit: " + "初始化成功");
            }
        }
    };


    private RecognizerListener mRecognizerListener = new RecognizerListener() {

        @Override
        public void onBeginOfSpeech() {
            LogUtil.i("开始说话");
        }

        @Override
        public void onError(SpeechError error) {
            mProgressDialog.dismiss();
            Toast.makeText(mContext, "您没有说话", Toast.LENGTH_SHORT).show();
//            // Tips：
//            // 错误码：10118(您没有说话)，可能是录音机权限被禁，需要提示用户打开应用的录音权限。
//            // 如果使用本地功能（语记）需要提示用户开启语记的录音权限。
//            if (mTranslateEnable && error.getErrorCode() == 14002) {
//                showTip(error.getPlainDescription(true) + "\n请确认是否已开通翻译功能");
//            } else {
//                showTip(error.getPlainDescription(true));
//            }
        }

        @Override
        public void onEndOfSpeech() {
            // 此回调表示：检测到了语音的尾端点，已经进入识别过程，不再接受语音输入
            // showTip("结束说话");
            LogUtil.i("结束说话");
            if (!isNormal) {
                mDialogManager.dimissDialog();
                mCurrentState = STATE_DOWN;
                setText("按下 说话");
                setBackground(ContextCompat.getDrawable(mContext, R.drawable.shape_btn_red));
                isActionUp = true;
                isCanRecord = true;
            }
        }


        @Override
        public void onResult(RecognizerResult results, boolean isLast) {

            String text = JsonParser.parseIatResult(results.getResultString());
            String sn = null;
            // 读取json结果中的sn字段
            try {
                JSONObject resultJson = new JSONObject(results.getResultString());
                sn = resultJson.optString("sn");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            mIatResults.put(sn, text);
            StringBuffer resultBuffer = new StringBuffer();
            for (String key : mIatResults.keySet()) {
                resultBuffer.append(mIatResults.get(key));
            }
            if (isLast) {
                mProgressDialog.dismiss();
                mListener.onFinished(resultBuffer.toString());
            }
        }

        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            mDialogManager.updateVoiceLevel(volume);
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id，当业务出错时将会话id提供给技术支持人员，可用于查询会话日志，定位出错原因
            // 若使用本地能力，会话id为null
            //	if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //		Log.d(TAG, "session id =" + sid);
            //	}
        }
    };


    public interface AudioFinishRecorderListener {
        void onFinished(String content);
    }

    private AudioFinishRecorderListener mListener;

    public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener) {
        mListener = listener;
    }
}
